/**
  ******************************************************************************
  * @file           : xgzp6847d.c
  * @author         : Mark Xiang
  * @brief          : brief
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */

/* ------------------------------ Includes ------------------------------ */
#include "xgzp6847d.h"
#include "stm32f1xx_hal.h"
#include "i2c.h"
/* ------------------------------ Defines ------------------------------ */
#define SENSOR_I2C hi2c1
/* ------------------------------ Private Function Declarations ------------------------------ */
static uint8_t prvReadReg(uint8_t reg_addr);
static void prvWriteReg(uint8_t reg_addr, uint8_t data);
/* ------------------------------ Public Function Declarations ------------------------------ */
static void Init(void);
static float ReadPressure(void);
/* ------------------------------ Variable Declarations ------------------------------ */

/* ------------------------------ Private ------------------------------ */

/**
  * @brief  Read register value.
  * @param  reg_addr register address
  * @retval register value
  */
static uint8_t prvReadReg(uint8_t reg_addr)
{
  uint8_t data;
  HAL_I2C_Mem_Read(&SENSOR_I2C, XGZP6847D_READ_ADDR, reg_addr, I2C_MEMADD_SIZE_8BIT, &data, 1, 1000);
  return data;
}

/**
  * @brief  Write data into register.
  * @param  reg_addr register address
  * @param  data data to write
  * @retval None
  */
static void prvWriteReg(uint8_t reg_addr, uint8_t data)
{
  HAL_I2C_Mem_Write(&SENSOR_I2C, XGZP6847D_WRITE_ADDR, reg_addr, I2C_MEMADD_SIZE_8BIT, &data, 1, 1000);
}

/* ------------------------------ Public ------------------------------ */

/**
  * @brief  Initiate XGZP6847D & set it to output corrected value.
  * @retval None
  */
static void Init(void)
{
  /* set sensor to output corrected value */
  uint8_t temp_config;
  temp_config = prvReadReg(MODE_CTRL_REG);
  temp_config &= 0xFD;
  prvWriteReg(MODE_CTRL_REG, temp_config);
}

/**
  * @brief  Get the value of pressure.
  * @retval pressure in kPa
  */
static float ReadPressure(void)
{
  /* read only pressure data */
  prvWriteReg(COMMAND_REG, TEMP_PRESS_BOTH);

  /* wait for completion */
  while(prvReadReg(COMMAND_REG) & 0x08)
  {}

  /* calculate pressure */
  uint8_t press_LSB, press_CSB, press_MSB;
  int32_t pressure_int;
  float pressure_float;
  press_LSB = prvReadReg(DATA_LSB_REG);
  press_CSB = prvReadReg(DATA_CSB_REG);
  press_MSB = prvReadReg(DATA_MSB_REG);
  pressure_int = press_LSB + (press_CSB << 8) + (press_MSB << 16);

  if(pressure_int >> 23)
  {
    pressure_int -= 16777216;
  }
  /* kPa */
  pressure_float = (float) pressure_int / 64 / 1000;

  return pressure_float;
}

/* ------------------------------ Manager Declaration ------------------------------ */

Xgzp6847dManager_typedef PressSensor = 
{
  Init,
  ReadPressure
};
